/**
 * 推送数据数据API
 */
var messageDAO = require('./models/message.js'); // 持久化工具
var redisHelper = require('./helper/redisHelper'); 
redisHelper = new redisHelper();  // redis工具类闭包

var express = require('express'); 
var app = express();
app.use(express.bodyParser()); // 使用中间件

// var APP_ID = "ec691bfe0d4b5b759d154c453ccd02cb";
// var APP_SECRET = "a07fc12f-2ca2-48bc-8276-f64fc13317bf";
var APP_ID = require('./config/config.js').APP_ID;
var APP_SECRET = require('./config/config.js').APP_SECRET; 

// 捕捉全局异常
process.on('uncaughtException', function(err) {
	console.error('uncaughtException: ' + err);
});

/**
 * [description] 全局过滤器
 * @param  {[type]}   req  [description]
 * @param  {[type]}   res  [description]
 * @param  {Function} next [description]
 * @return {[type]}        [description]
 */
app.all('/*', function(req, res, next) {
	console.log('all methods captured'); 

	if (APP_ID !== req.body.appId || APP_SECRET !== req.body.secret) {
		res.status(401).json({result: false, 'message': 'request validation fail.'});
		return;
	};
	next(); 
});

/**
 * [description] 推送消息
 * @param  {[type]} req [description]
 * @param  {[type]} res [description]
 * @return {[type]}     [description]
 */
app.post('/pushMsg', function(req, res) {
	console.log('--------------------------------------------------------');
	console.log('\n--------------------------------------------------------');
	console.log('Request：request coming：' + req.ip);
	console.log('Request body:');
	console.log(req.body); // msg应该带有设备id

	// step1 获取msg
	var msg = req.body.msg;
	var deviceId = req.body.deviceId;

	if (deviceId === undefined || deviceId === '') {
		res.status(401).json({result: false, 'message': 'request validation fail. no deviceId...'});
		return;
	};

	/**
	 * 根据设备发送消息
	 */
	redisHelper.get(deviceId + '_sockets', function(error, reply) {
		// var connections = require('./connector.js').getConnects(); // 获取队列实体

		if(!error) {
			msg = eval("(" + msg + ")"); // 转换msg对象
			// msg: '{"id":"17d70aabfb0742e486407930f661c40a","title":"公告","messageType":"MODULE","extras":{"moduleIdentifer":"com.foss.announcement"}}',
			// deviceId: '00000000-4df8-d963-3b64-93f651a1e20a'
			var message = {
				msgId: msg.id,
				msgType: msg.messageType,
				title: msg.title,
				target: deviceId
			}
			if(msg.extras) { // 存在扩展信息情况，例如推送公告
				message.extras = msg.extras;
			}
			if(msg.content) {
				message.content = msg.content; // 带有内容的消息，不需要拉取完整信息
			}
			console.log('step1 开始保存日志：' + message.msgId);
			if (reply) { // 说明此socktet在长连接队列中 
				// mongo更新成功状态，变色龙特有
				// message.receive = true; 
				messageDAO.save(message, function(err) {
					if (err) {
						console.error('插入message对象异常：' + err);
					}
					console.log('step2 开始发送消息：' + 'socket队列=' + reply + ' --> ' + deviceId);
					var server = require('./connector.js');
					server = new server();
					var flag = server.writeMsg(reply.valueOf(), msg);
					// var flag = require('./connector.js')(reply.valueOf(), msg); // 获取队列实体
					console.log("flag=" + flag);
					// connections[reply.valueOf()].write(msgpack.packWithType(msg, 1)); // 推送给客户端APP
					res.status(200).json(flag ? 200 : 500); // eclipse
				});
			} else {
				console.log('此设备未保持长连接，不过没关系，登录长连接后它会去平台拉取离线消息！');
				messageDAO.save(message, function(err) {
					if (err) {
						console.error('插入message对象异常：' + err);
					}
				});
				res.status(200).json(304);
			}
		} else { // redis连接器异常
			res.status(200).json(500); // eclipse
		}
	});
});

/**
 * [description] 拉取完整消息（1推送长消息没有消息内容，2短消息直接推送过去；包含content为长消息！）
 * @param  {[type]} req [description]
 * @param  {[type]} res [description]
 * @return {[type]}     [description]
 */
app.get('/v1/message/:appId/:secret?msgId=xxx&timestamp=xxx', function(req, res) {
	console.log('--------------------------------------------------------');
	console.log('\n--------------------------------------------------------');
	console.log('Request：request coming：' + req.ip);
	console.log('Request body:');
	console.log(req.body); // msg应该带有设备id {a:buffer.SlowBuffer();}

	// step1 获取msgId
	var msgId = req.params.msgId;
	var timestamp = req.params.timestamp;

	if (msgId === undefined || msgId === '') {
		res.status(401).json({result: false, 'message': 'request validation fail. no msgId...'});
		return;
	};

	// step2 根据msgId持久化message回执
	var conditions = {msgId: msgId},
		update = {
			receive: true, 
			receiveTime: new Date(Date.parse(timestamp))
		};
	messageDAO.findOneAndUpdate(conditions, update, function(err, Message) {
		if(err) {
			console.error('mongodb operate exception...\n' + err);
			res.status(500).json({result: false, message: 'server exception. '});
		} else {
			console.log('更新成功，Message.receive=' + Message.receive);
			res.status(200).json({result: true, message: Message});
		}
	});
});

/**
 * [description] 消息回执 http://ip:port/v1/message/:appId/:secret/:msgId/:timestamp
 * @param  {[type]} req [description]
 * @param  {[type]} res [description]
 * @return {[type]}     [description]
 */
app.put('/v1/message/:appId/:secret/:msgId/:timestamp', function(req, res) {
	console.log('--------------------------------------------------------');
	console.log('\n--------------------------------------------------------');
	console.log('Request：request coming：' + req.ip);
	console.log('Request body:');
	console.log(req.body); // msg应该带有设备id {a:buffer.SlowBuffer();}

	// step1 获取msgId
	var msgId = req.params.msgId;
	var timestamp = req.params.timestamp;

	if (msgId === undefined || msgId === '') {
		res.status(401).json({result: false, message: 'request validation fail. no msgId...'});
		return;
	};
	// step2 根据msgId持久化message回执
	var conditions = {msgId: msgId},
		update = {
			receive: true, 
			receiveTime: new Date()
		};
	messageDAO.findOneAndUpdate(conditions, update, function(err, Message) {
		if(err) {
			console.error('mongodb operate exception...\n' + err);
			res.status(500).json({result: false, message: 'server exception. '});
		} else {
			console.log('更新成功，Message.receive=' + Message.receive);
			res.status(200).json({result: true, message: 'has recived.'});
		}
	});
});

//######## commonjs interface #################
module.exports = function() {	
	app.listen(/*process.env.PORT ||*/8869);
	console.log('Push API server bound, port:8869.');
};
